/*
 * Copyright (C) 2010 TTPASI, Inc. All Rights Reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS-IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package ttpasi.jgenere.initial_port;

import static java.lang.Character.toLowerCase;
import static java.lang.Character.toUpperCase;

/**
 * Used by Caesar, Vigenere, and VigCrack algorithms.
 * 
 * @author  Bruce [com.gmail @ ProgrammerBruce]
 * @version 2010.1105
 */
class Utils
{
  final static char[] Aa = {'A', 'a'};

  /**
   * Returns letter wrapped within range of A-Z or a-z, per target case.
   * <p/>
   * Used by algorithms that don't otherwise wrap shifted letter values.
   * 
   * @param     targetCase  Indicates upper or lower alphabet case.
   * @param     letter      Shifted letter, possibly needing to be wrapped.
   * @return    Value of target letter wrapped within English alphabet range.
   */
  static int shiftBackIntoAlphabet(char targetCase, int letter)
  {
    if (isUpper(targetCase))
    {
      while (letter < 65)
      {
        letter += 26;
      }
      while (letter > 90)
      {
        letter -= 26;
      }
    }
    else if (isLower(targetCase))
    {
      while (letter < 97)
      {
        letter += 26;
      }
      while (letter > 122)
      {
        letter -= 26;
      }
    }
    return letter;
  }

  /**
   * Shifts the caesarShift into number range 0 to 25.
   * <p/>
   * Used by Caesar algorithms, because wrapping repeatedly is unnecessary.
   * 
   * @param     caesarShift The value that may be out of range 0 to 25.
   * @return    The caesarShift shifted into number range 0 to 25.  
   */
  static int fixAndMakePositive(int caesarShift)
  {
    caesarShift %= 26;
    if (caesarShift < 0)
    {
      caesarShift += 26;
    }
    return caesarShift;
  }

  /**
   * Returns true if the character is upper case in the English alphabet.
   * <p/>
   * Not using Character.isUpperCase(char) because I have not been able to 
   * determine all values in the general category 'Lu' in the Unicode 
   * specification.
   * 
   * @param     p The target character.
   * @return    true if the target is an upper case English alphabet character.
   */
  private static boolean isUpper(char p)
  {
    return (p >= 'A' && p <= 'Z');
  }

  /**
   * Returns true if the character is lower case in the English alphabet.
   * <p/>
   * Not using Character.isLowerCase(char) for same reasons listed in 
   * {@link #isUpper(char)}
   * 
   * @param     p The target character.
   * @return    true if the target is a lower case English alphabet character.
   */
  private static boolean isLower(char p)
  {
    return (p >= 'a' && p <= 'z');
  }

  /**
   * Returns true if the character is in the English alphabet.
   * <p/>
   * Not using Character.isLetter(char) for same reasons listed in 
   * {@link #isUpper(char)}
   * 
   * @param     p The target character.
   * @return    true if the target is an English alphabet character.
   */
  static boolean isAlpha(char p)
  {
    return isUpper(p) || isLower(p);
  }

  /**
   * Returns 1 if the target character is is lower case; 0 otherwise.
   * <p/>
   * Used by Caesar and Vigenere algorithms to select either 'a' or 'A', per 
   * case of target character.
   * 
   * @param     p The target character.
   * @return    1 if the target character is is lower case; 0 otherwise.
   */
  static int lower(char p)
  {
    return isLower(p) ? 1 : 0;
  }

  /**
   * Returns an array comprised of the upper and lower cases of the target char.
   * <p/>
   * The generated array has a length of two.  The first component is the upper 
   * case letter.  The second component is the lower case letter.
   * 
   * @param     key The String within which to retrieve the target character.
   * @param     k The index of the target character.  May be out of range of the 
   *            provided String key indexes.
   * @param     n The length of the provided String key.  Technically, not 
   *            required as a parameter to this method, since the length of the 
   *            key can otherwise easily be determined.  Included since PyGenere
   *            uses it, and wanted to mimic PyGenere for initial port to Java.
   * @return    array of upper and lower cases of target character.
   */
  static char[] upperAndLowerChars(final String key, int k, int n)
  {
    int index = k % n;
    char character = key.charAt(index);
    char upperCase = toUpperCase(character);
    char lowerCase = toLowerCase(character);
    return new char[] {upperCase, lowerCase};
  }
}
